%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2019, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 23. 12月 2019 13:01
%%%-------------------------------------------------------------------
-module(player_assist).
-author("Administrator").
-include("include/protocol.hrl").
-include("include/uri.hrl").
-include("include/player.hrl").
-include("include/myshare.hrl").
-include("include/logger.hrl").
-include("include/game.hrl").
%% API
-export([login/1, assemblePlayerData/1, get_player_account/0, get_player_state/0, get_at_player_info/0,
  get_player_info/1, update_player_info/2, update_player_key_info/3, ws_pid/0, get_first_room/1, command/1
  , player_queue/2, delete_queue/2, room_queue_number/1, is_in_room/3, delete_player_key_info/1, delete_room_key_info/1,
  delete_player_task/2, player_logout/2, test/0, get_player_info_id/1, get_all_player_id/0, restart/1, next_task/1
  , new_account_login/2]).

restart(Account) ->
  Ret2 = player_assist:get_player_info(Account),
  PlayerPid = Ret2#player_info.pid,
  gen_server:call(PlayerPid, {stop}),
  player_assist:login(Ret2).

login(#player_info{account = Account, password = Password} = PlayerRecord) ->
  %%  开始登录
  ?INFO("User start login player record:~p", [PlayerRecord]),
  Record = #user_login{account = Account, password = Password},
  ReqMap = ?record_to_map(?UserLogin, Record),
  Body = sys_util:map2formBinary(ReqMap),
  case sys_util:http_post_request(?HTTP_USER_LOGIN, Body) of
    {ok, Content} ->
      ContentMap = jsx:decode(Content, [return_maps, {labels, atom}]),
      {ok, Data} = maps:find(data, ContentMap),
      Token = binary_to_list(Data),
      %%分裂玩家进程
      player_sup:addChild([PlayerRecord#player_info{token = Token}]);
    {error, _} ->
      ?ERROR("login fail:~p", [Body]),
      ok
  end.

get_all_player_id() ->
  Players = ets:tab2list(?ETS_PLAYER_INFO),
  lists:foldl(
    fun(Player, Acc) ->
      [Player#player_info.id | Acc]
    end, [], Players).


%%拼装玩家db数据到record
assemblePlayerData(List) ->
  Fun = fun(In, Out) ->
    [Account, Password, Is_new_player] = In,
    PlayerInfo = #player_info{account = binary_to_list(Account),
      password = binary_to_list(Password),
      channel = ?Channel,
      is_new_player = Is_new_player
    },
    [PlayerInfo | Out]
        end,
  lists:foldl(Fun, [], List).

%%获取玩家状态信息
get_player_state() ->
  erlang:get(?PLAYER_STATE).

%%获取当前玩家account
get_player_account() ->
  PlayerState = get_player_state(),
  Account = PlayerState#player_state.account,
  Account.

%%根据id查玩家信息
get_player_info_id(PlayerId) ->
  Players = ets:tab2list(?ETS_PLAYER_INFO),
  lists:keyfind(PlayerId, 6, Players).

%%获取玩家信息
get_player_info(Account) ->
  case ets:lookup(?ETS_PLAYER_INFO, Account) of
    [] -> [];
    [PlayerInfo] -> PlayerInfo
  end.

%%获取当前进程玩家信息
get_at_player_info() ->
  Account = get_player_account(),
  PlayerInfo = get_player_info(Account),
  PlayerInfo.

%%更新用户信息
update_player_info(Account, FiledList) ->
  ets:update_element(?ETS_PLAYER_INFO, Account, FiledList).

%%更新用户某个信息
update_player_key_info(Account, Key, Value) ->
  ets:update_element(?ETS_PLAYER_INFO, Account, {Key, Value}).

%%删除某个玩家
delete_player_key_info(Account) ->
  ets:delete(?ETS_PLAYER_INFO, Account).

%%删除玩家房间数据
delete_room_key_info(Account) ->
  ets:delete(?ETS_ROOM_INFO, Account).


%% 当前玩家ws conn pid
-spec ws_pid() -> pid().
ws_pid() ->
  PlayerState = get_player_state(),
  ConnPid = PlayerState#player_state.ws_connPid,
  ConnPid.

%%获取最早创建的房间
-spec get_first_room(Account :: string()) -> #room_data{} | list().
get_first_room(Account) ->
  case ets:lookup(?ETS_ROOM_INFO, Account) of
    [] -> [];
    [AccountRooms] ->
      case AccountRooms#room_info.room_list of
        [] -> [];
        ok -> [];
        Rooms ->
          RoomInfo = erlang:hd(Rooms),
          Invalid_date = sys_util:date_string_to_timestamp(RoomInfo#room_data.invalid_date) + 120,
          Now = sys_util:timestamp(),
          if
            Now > Invalid_date ->
              NewRooms = lists:delete(RoomInfo, Rooms),
              ets:update_element(?ETS_ROOM_INFO, Account, {#room_info.room_list, lists:keysort(#room_data.create_date, NewRooms)}),
              get_first_room(Account);
            true ->

              case RoomInfo#room_data.game_type of
                ?NIU_NIU_MING_PAI ->
                  %%明牌一个房间只进8个人
                  Room_number =
                    case ets:lookup(?ETS_MING_PAI_ROOM_NUMBER, RoomInfo#room_data.room_id) of
                      [] ->
                        0;
                      [#ming_pai_room_number{number = Number2}] ->
                        Number2
                    end,
                  if
                    Room_number > 7 ->
                      NewRooms = lists:delete(RoomInfo, Rooms),
                      ets:update_element(?ETS_ROOM_INFO, Account, {#room_info.room_list, lists:keysort(#room_data.create_date, NewRooms)}),
                      get_first_room(Account);
                    true -> RoomInfo
                  end;
                _ -> RoomInfo
              end
          end
      end
  end.


%%某个房间排队人数
-spec room_queue_number(RoomId :: string()) -> none().
room_queue_number(RoomId) ->
  case ets:lookup(?ETS_ROBOT_QUEUE, RoomId) of
    [] -> 0;
    [Queue] ->
      IndexInfo = Queue#robot_queue.index,
      Fun2 = fun(_K, V, Acc) ->
        Num = erlang:length(V),
        Acc + Num
             end,
      maps:fold(Fun2, 0, IndexInfo)
  end.


%%加入玩家排队表
-spec player_queue(RoomId :: string(), PlayerId :: string()) -> none().
player_queue(RoomId, PlayerId) ->
  [Queue] = ets:lookup(?ETS_ROBOT_QUEUE, RoomId),
  IndexInfo = Queue#robot_queue.index,
  Fun2 = fun(K, V, Acc) ->
    case lists:member(PlayerId, V) of
      true -> [0, -1];
      _ ->
        Num = erlang:length(V),
        case Acc of
          [] -> [K, Num];
          _ ->
            [_, N] = Acc,
            if
              Num >= N -> Acc;
              true -> [K, Num]
            end
        end
    end
         end,
  [Index2, Num2] = maps:fold(Fun2, [], IndexInfo),
  PlayerList = maps:get(Index2, IndexInfo),
  case Num2 of
    -1 -> normal;
    _ ->
      List2 = PlayerList ++ [PlayerId],
      Map2 = IndexInfo#{Index2 => List2},
      ets:update_element(?ETS_ROBOT_QUEUE, RoomId, {#robot_queue.index, Map2}),
      Index2
  end.

%%从排队表删除
-spec delete_queue(RoomId :: string(), PlayerId :: string()) -> none().
delete_queue(RoomId, PlayerId) ->
  [Queue] = ets:lookup(?ETS_ROBOT_QUEUE, RoomId),
  IndexInfo = Queue#robot_queue.index,
  Fun2 = fun(_K, List)
    ->
    case List of
      [] -> [];
      _ -> lists:delete(PlayerId, List)
    end
         end,
  Map2 = maps:map(Fun2, IndexInfo),
  ets:update_element(?ETS_ROBOT_QUEUE, RoomId, {#robot_queue.index, Map2}).

%%根据房间数据判断是否已在房间里
-spec is_in_room(Players :: list(), LookPlayers :: list(), PlayerId :: list()) -> boolean().
is_in_room(Players, LookPlayers, PlayerId) ->
  Fun2 = fun(Player) ->
    Id = maps:get(id, Player),
    PlayerId =:= binary_to_list(Id)
         end,
  Ret2 = lists:filter(Fun2, Players),
  Fun3 = fun(Player) ->
    Id = maps:get(id, Player),
    PlayerId =:= binary_to_list(Id)
         end,
  Ret3 = lists:filter(Fun3, LookPlayers),
  Ret2 /= [] orelse Ret3 /= [].

%%批量进入房间
command(Command) ->
  Players = ets:tab2list(?ETS_PLAYER_INFO),
  NewCommand =
    case Command of
      in_room -> {into_game_room, 102815};
      into_integral -> {game, {into_integral, 1000}};
      out_room -> {game, {out_room}};
      player_bet -> {game, {player_bet}};
      join_table -> {game, {join_table}};
      stand_look -> {game, {stand_look}};
      checkout -> {game, {checkout}};
      checkout_request -> {game, {checkout_request}};
      stop -> stop
    end,

  Fun2 = fun(Player) ->
    Pid = Player#player_info.pid,
    ?INFO("send command pid:~p;command: ~p~n", [Pid, NewCommand]),
    case NewCommand of
      stop ->
        gen_server:cast(Pid, {stop});
      _ ->
        erlang:send_after(2000, Pid, NewCommand)
    end
         end,
  lists:foreach(Fun2, Players).

test() ->
  Pid = list_to_atom("pid_" ++ "86-88888097"),
  State = gen_server:call(Pid, {player_state}),
  ?DEBUG("player state :~p", [State]).

%%删除任务数据
delete_player_task(TaskId, Account) ->
  case ets:lookup(?ETS_GAME_TASK, TaskId) of
    [] -> ok;
    [Task] ->
      PlayerList = Task#game_task.player_list,
      ?DEBUG("playerList delete:list:~p,playerId:~p", [PlayerList, Account]),
      TaskPlayerList =
        lists:foldl(
          fun(PI2 = #game_task_player{account = Account2}, Acc2) ->
            case Account2 of
              Account -> Acc2;
              _ -> [PI2 | Acc2]
            end
          end, [], PlayerList),
      ets:update_element(?ETS_GAME_TASK, TaskId, {#game_task.player_list, TaskPlayerList})
  end.

%%玩家退出登录
player_logout(_PlayerPid, State) ->
  pool_player:put_player(State#player_state.account, State#player_state.password),
  if
    erlang:is_pid(State#player_state.game_pid) ->
      gen_server:call(State#player_state.game_pid, {stop});
    true ->
      ok
  end,
  database:update_logout_state(State#player_state.account),
  %删除任务表数据
  player_assist:delete_player_task(State#player_state.task_id, State#player_state.account),
  %删除玩家数据
  player_assist:delete_player_key_info(State#player_state.account),
  %删除玩家房间数据
  player_assist:delete_room_key_info(State#player_state.account),
  ets:delete(?ETS_PLAYER_INTO_ROOM, State#player_state.account),
  ets:delete(?ETS_PLAYER_PROTOCOL, State#player_state.account).

%%登陆新账号
new_account_login(Task_id, Is_look_bet) ->
  Minutes = sys_util:random(3000) + sys_util:random(8000),
  erlang:send_after(Minutes, mainPID, {subs, Task_id, Is_look_bet}).


%%下一个任务
next_task(State = #player_state{task_id = Task_id, account = Account, room_id = Room_id}) ->
  case check_task_min_30mins(Task_id) of
    true ->
      game_assist:delete_player_room(Account, Room_id),
      Min = 3000 + sys_util:random(4000),
      case player_assist:get_first_room(Account) of
        #room_data{game_type = GameId, room_id = RoomId, type = RoomType} ->
          ?DEBUG("Move on to the next task:gameid:~p,roomID:~p", [GameId, RoomId]),
          case State#player_state.game_id of
            GameId ->
              ?DEBUG("Into a new room GameId:~p;roomID:~p,account:~p", [GameId, RoomId, Account]),
              case is_pid(State#player_state.game_pid) andalso is_process_alive(State#player_state.game_pid) of
                true -> self() ! {into_game_room, RoomId};
                _ -> erlang:send_after(Min, self(), {start_game, GameId, RoomId, RoomType})
              end;
            _ ->
              ?DEBUG("Close the current game:~p and start a new game:~p", [State#player_state.game_id, GameId]),
              gen_server:cast(State#player_state.game_pid, {stop}),
              erlang:send_after(Min, self(), {start_game, GameId, RoomId, RoomType})
          end;
        _ ->
          ?INFO("No new mission room account:~p", [Account]),
          case is_pid(State#player_state.game_pid) andalso is_process_alive(State#player_state.game_pid) of
            true -> gen_server:cast(State#player_state.game_pid,{stop});
            _ -> ok
          end,
          ok
      end;
    _ ->
      ?INFO("Task time remaining is less than 30 minutes account:~p", [Account]),
      ok
  end.

%%验证任务是否剩余时间小于30分钟false是小于
check_task_min_30mins(TaskId) ->
  Now = sys_util:timestamp(),
  case game_assist:get_task_info(TaskId) of
    #game_task{end_at = End_At, is_all_day_run = Is_all_day_run} ->
      case Is_all_day_run of
        true -> true;
        _ ->
          NewTime = End_At - 1800,
          case NewTime > Now of
            true -> true;
            _ -> false
          end
      end;
    _ -> false
  end.




